"""
至少有两种错误：句法错误和异常

异常
就算语句和表达式都采用了正确的语法，在运行期间仍旧可能引发错误

参考文档：https://docs.python.org/zh-cn/3/tutorial/errors.html#exceptions
"""

def testHandleExceptions():
    """异常处理
    Try语句的工作原理如下：
    首先，执行try子句（try和except关键字之间的（多行）语句）
    如果没有触发异常，则跳过except子句，try语句执行完毕。

    如果在执行try子句时发生了异常，则跳过该子句中剩下的部分。
    如果异常的类型与except关键字后指定的异常相匹配，则会执行except子句，然后跳到try/except代码块之后继续执行。

    如果发生的异常与except子句中指定的异常不匹配，则它会被传递到外部的try语句中；
    如果没有找到处理程序，则它是一个未处理异常，且执行将终止并输出如上所示的消息。
    """

    # 模仿一个除0异常
    exceptionHandled = False

    try:
        # 除0异常
        result = 10 / (1 * 0)

        # 执行不到这个语句
        assert result
    except ZeroDivisionError:
        exceptionHandled = True

    print("exceptionHandled is {}".format(exceptionHandled))

    # try语句可以有多个except子句来为不同的异常指定处理程序。但最多只有一个处理程序会被执行
    # 处理程序只处理对应的try子句中发生的异常，而不处理同一try语句内其他处理程序中的异常。 
    # except子句可以用带圆括号的元组来指定多个异常

    exceptionHandled = False
    try:
        result = 1 * (1 / 0)
        assert result
    # 使用()
    except (ZeroDivisionError, NameError):
        exceptionHandled = True
    print("exceptionHandled is {}".format(exceptionHandled))

    # 
    exceptionHandled = False
    try:
        result = 1 * (1 / 0)
        assert result
    except NameError:
        # 这里会被执行
        exceptionHandled = True
        print("NameError exceptionHandled is {}".format(exceptionHandled))
    except ZeroDivisionError:
        # 这里也会被执行
        exceptionHandled = True
        print("ZeroError exceptionHandled is {}".format(exceptionHandled))
    
    print("exceptionHandled is {}".format(exceptionHandled))

    # try ... except语句具有可选的else子句，该子句如果存在，它必须放except子句之后。 
    # 它适用于try子句没有引发异常但又必须要执行的代码
    exceptionHandled = False
    noException =  False
    try:
        result = 10
        # 会不会执行下面的语句呢
        print("result is {} with try else clause".format(result))
    except NameError:
        exceptionHandled = True
    else:
        noException = True

    print("not exceptionHandled is {}".format(not exceptionHandled))
    print("noException is {}".format(noException))

testHandleExceptions()
